//
//  LLNWRequestManager.m
//  LLFoundation
//
//  Created by my_liu on 2016/11/14.
//  Copyright © 2016年 . All rights reserved.
//

#import "LLNWRequestManager.h"

@interface LLNWRequestManager ()

@property (nonatomic, strong) NSMutableDictionary *requestDict;

@end

@implementation LLNWRequestManager

- (id)initWithBaseURL:(NSURL *)url
{
    self = [super initWithBaseURL:url];
    if (self) {
        _requestDict = [NSMutableDictionary dictionary];
        self.securityPolicy =  [AFSecurityPolicy defaultPolicy];
        self.securityPolicy.allowInvalidCertificates = YES;
        self.responseSerializer = [AFJSONResponseSerializer serializer];
        ((AFJSONResponseSerializer *)self.responseSerializer).removesKeysWithNullValues = YES;
        NSMutableSet *contentTypes = [NSMutableSet set];
        [contentTypes addObject:@"application/json"];[contentTypes addObject:@"text/json"];
        [contentTypes addObject:@"text/javascript"];[contentTypes addObject:@"text/html"];
        [contentTypes addObject:@"text/css"];[contentTypes addObject:@"image/png"];
        self.responseSerializer.acceptableContentTypes = contentTypes;
    }
    return self;
    
}

- (void)cancelRequestWithRequestKey:(NSString *)requestKey
{
    NSURLSessionDataTask *dataTask = [_requestDict objectForKey:requestKey];
    if (dataTask) {
        [dataTask cancel];
    }
}

- (void)addAFHTTPHeader:(LLNWHTTPDetails *)requestInfo
{
    if (requestInfo.appendHeader) {
        for (NSString *key in requestInfo.appendHeader.allKeys) {
            [self.requestSerializer setValue:[[requestInfo.appendHeader objectForKey:key] description] forHTTPHeaderField:key];
        }
    }
}

- (void)setRequestHTTPBody:(NSMutableURLRequest *)request requestInfo:(LLNWHTTPDetails *)requestInfo
{
    if (requestInfo.parameters) {
        return;
    }
    NSMutableData *postData = [[NSMutableData alloc] init];
    NSMutableString *bodyString = [[NSMutableString alloc] init];
    for (NSString *key in requestInfo.dictBody.allKeys) {
        NSString *obj = [requestInfo.dictBody objectForKey:key];
        NSString *param_value = [NSString stringWithFormat:@"%@=%@",key,obj];
        [bodyString appendFormat:@"%@&",param_value];
    }
    [postData appendData:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
    if (requestInfo.stringBody) {
        [postData appendData:[requestInfo.stringBody dataUsingEncoding:NSUTF8StringEncoding]];
    }
    if (requestInfo.requestBody) {
        [postData appendData:requestInfo.requestBody];
    }
    [request setHTTPBody:postData];
}

- (void)start:(id)manager withInfo:(LLNWHTTPDetails *)requestInfo success:(void(^)(LLNWHTTPResponse *response))success failure:(void(^)(LLNWHTTPResponse *response))failure {
    [self addAFHTTPHeader:requestInfo];
    if ([requestInfo.requestMethod isEqualToString:kLLNWPostMethod]) {
        [self post:manager withInfo:requestInfo success:success failure:failure];
    } else if ([requestInfo.requestMethod isEqualToString:kLLNWGetMethod]) {
        [self get:manager withInfo:requestInfo success:success failure:failure];
    }
    //    else if ([requestInfo.requestMethod isEqualToString:kLLNWDELEMethod]) {
    //        [self delete:manager withInfo:requestInfo success:success failure:failure];
    //    } else if ([requestInfo.requestMethod isEqualToString:kLLNWPUTMethod]) {
    //        [self post:manager withInfo:requestInfo success:success failure:failure];
    //    }
}

- (void)post:(id)manager withInfo:(LLNWHTTPDetails *)requestInfo success:(void(^)(LLNWHTTPResponse *response))success failure:(void(^)(LLNWHTTPResponse *response))failure
{
    if (requestInfo.parameters) {
        self.requestSerializer = requestInfo.requestSerializer;
    }
    
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:requestInfo.requestMethod URLString:requestInfo.requestHost parameters:requestInfo.parameters error:&serializationError];
    if (serializationError) {
        if (failure) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu"
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil);
            });
#pragma clang diagnostic pop
        }
        
        return ;
    }
    
    __block NSURLSessionDataTask *dataTask = nil;
    LLNWHTTPResponse *response = [[LLNWHTTPResponse alloc] init];
    dataTask = [self dataTaskWithRequest:request
                          uploadProgress:nil
                        downloadProgress:nil
                       completionHandler:^(NSURLResponse * __unused res, id responseObject, NSError *error) {
                           if (error) {
                               if (failure) {
                                   if(requestInfo.requestKey) {
                                       [self.requestDict removeObjectForKey:requestInfo.requestKey];
                                   }
                                   if(error.code == NSURLErrorCancelled) {
                                       response.networkState = LLNWHTTPNetworkIsCancelled;
                                   }
                                   if (failure) {
                                       if ([LLNWHTTPLink checkNetworkConnection]) {
                                           if (response.networkState < LLNWHTTPNetworkIsCancelled) {
                                               if (error.code == -1001) {
                                                   response.networkState = LLNWHTTPNetworkTimedOut;
                                               } else {
                                                   response.networkState = LLNWHTTPNetworkServerError;
                                               }
                                           }
                                       } else {
                                           response.networkState = LLNWHTTPNotNetworkState;
                                       }
                                       response.error = error;
                                       response.urlResponse = res;
                                       response.responseData = responseObject;
                                       failure(response);
                                   }
                               }
                           } else {
                               if (success) {
                                   if(requestInfo.requestKey) {
                                       [self.requestDict removeObjectForKey:requestInfo.requestKey];
                                   }
                                   if (success) {
                                       response.networkState = LLNWHTTPNetworkNormal;
                                       response.urlResponse = res;
                                       response.responseData = responseObject;
                                       success(response);
                                   }
                               }
                           }
                       }];
    
    if(requestInfo.requestKey) {
        [self.requestDict setObject:dataTask forKey:requestInfo.requestKey];
    }
    [dataTask resume];
}

- (void)get:(id)manager withInfo:(LLNWHTTPDetails *)requestInfo success:(void(^)(LLNWHTTPResponse *response))success failure:(void(^)(LLNWHTTPResponse *response))failure {
    LLNWHTTPResponse *response = [[LLNWHTTPResponse alloc] init];
    
    NSURLSessionDataTask *dataTask = [self GET:requestInfo.requestHost parameters:requestInfo.parameters progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if(requestInfo.requestKey) {
            [self.requestDict removeObjectForKey:requestInfo.requestKey];
        }
        if (success) {
            response.networkState = LLNWHTTPNetworkNormal;
            response.urlResponse = task.response;
            response.responseData = responseObject;
            success(response);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (requestInfo.requestKey) {
            [self.requestDict removeObjectForKey:requestInfo.requestKey];
        }
        if (error.code == NSURLErrorCancelled) {
            response.networkState = LLNWHTTPNetworkIsCancelled;
        }
        if (failure) {
            if ([LLNWHTTPLink checkNetworkConnection]) {
                if (response.networkState < LLNWHTTPNetworkIsCancelled) {
                    if (error.code == -1001) {
                        response.networkState = LLNWHTTPNetworkTimedOut;
                    } else {
                        response.networkState = LLNWHTTPNetworkServerError;
                    }
                }
            } else {
                response.networkState = LLNWHTTPNotNetworkState;
            }
            response.error = error;
            response.urlResponse = task.response;
            response.responseData = response;
            failure(response);
        }
    }];
    
    if (requestInfo.requestKey) {
        [self.requestDict setObject:dataTask forKey:requestInfo.requestKey];
    }
    
    [dataTask resume];
}

- (void)delete:(id)manager withInfo:(LLNWHTTPDetails *)requestInfo success:(void(^)(LLNWHTTPResponse *response))success failure:(void(^)(LLNWHTTPResponse *response))failure {
    LLNWHTTPResponse *response = [[LLNWHTTPResponse alloc] init];
    NSURLSessionDataTask *dataTask = [self DELETE:requestInfo.requestHost parameters:requestInfo.parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (requestInfo.requestKey) {
            [self.requestDict removeObjectForKey:requestInfo.requestKey];
        }
        if (success) {
            response.networkState = LLNWHTTPNetworkNormal;
            response.urlResponse = task.response;
            response.responseData = responseObject;
            success(response);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (requestInfo.requestKey) {
            [self.requestDict removeObjectForKey:requestInfo.requestKey];
        }
        if(error.code == NSURLErrorCancelled) {
            response.networkState = LLNWHTTPNetworkIsCancelled;
        }
        if (failure) {
            if ([LLNWHTTPLink checkNetworkConnection]) {
                if (response.networkState < LLNWHTTPNetworkIsCancelled) {
                    if (error.code == -1001) {
                        response.networkState = LLNWHTTPNetworkTimedOut;
                    } else {
                        response.networkState = LLNWHTTPNetworkServerError;
                    }
                }
            } else {
                response.networkState = LLNWHTTPNotNetworkState;
            }
            response.error = error;
            response.urlResponse = task.response;
            failure(response);
        }
    }];
    if (requestInfo.requestKey) {
        [self.requestDict setObject:dataTask forKey:requestInfo.requestKey];
    }
    [dataTask resume];
}

- (void)put:(id)manager withInfo:(LLNWHTTPDetails *)requestInfo success:(void(^)(LLNWHTTPResponse *response))success failure:(void(^)(LLNWHTTPResponse *response))failure {
    LLNWHTTPResponse *response = [[LLNWHTTPResponse alloc] init];
    
    NSURLSessionDataTask *dataTask = [self PUT:requestInfo.requestHost parameters:requestInfo.parameters success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        if (requestInfo.requestKey) {
            [self.requestDict removeObjectForKey:requestInfo.requestKey];
        }
        if (success) {
            response.networkState = LLNWHTTPNetworkNormal;
            response.urlResponse = task.response;
            response.responseData = responseObject;success(response);
        }
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if (requestInfo.requestKey) {
            [self.requestDict removeObjectForKey:requestInfo.requestKey];
        }
        if (error.code == NSURLErrorCancelled) {
            response.networkState = LLNWHTTPNetworkIsCancelled;
        }
        if (failure) {
            if ([LLNWHTTPLink checkNetworkConnection]) {
                if (response.networkState < LLNWHTTPNetworkIsCancelled) {
                    if (error.code == -1001) {
                        response.networkState = LLNWHTTPNetworkTimedOut;
                    } else {
                        response.networkState = LLNWHTTPNetworkServerError;
                    }
                }
            } else {
                response.networkState = LLNWHTTPNotNetworkState;
            }
            response.error = error;
            response.urlResponse = task.response;
            failure(response);
        }
    }];
    if (requestInfo.requestKey) {
        [self.requestDict setObject:dataTask forKey:requestInfo.requestKey];
    }
    [dataTask resume];
}

@end
